package jp.dip.ysato.excite;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import jp.dip.ysato.excite.DBHelper;
import jp.dip.ysato.excite.LoginActivity;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.telephony.TelephonyManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView;
import android.widget.ToggleButton;

public class MainActivity extends Activity {
	class SIM {
		private boolean fast;
		private String tel;
		public boolean isFast() {
			return fast;
		}
		public void setFast(boolean fast) {
			this.fast = fast;
		}
		public String getTel() {
			return tel;
		}
		public void setTel(String tel) {
			this.tel = tel;
		}
	}
	class Coupon {
		private String[] remain = new String[5];
		private Calendar[] month = new Calendar[4];
		private SIM[] sims = new SIM[3];
		public String getRemain(int index) {
			return remain[index];
		}
		public void setRemain(int index, String remain) {
			this.remain[index] = remain;
		}
		public Calendar getMonth(int index) {
			return month[index];
		}
		public void setMonth(int index, String date) {
			Pattern p = Pattern.compile("(\\d+)/(\\d+)");
			Matcher m = p.matcher(date);
			m.find();
			GregorianCalendar cal = new GregorianCalendar(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)) - 1, 1); 
			this.month[index] = cal;
		}
		public SIM getSIM(int index) {
			return sims[index];
		}
		public void setSIM(int index, SIM sim) {
			sims[index] = sim;
		}
	}
	private CookieStore getLoginCookie(String user, String pass) throws ClientProtocolException, IOException {
		DefaultHttpClient httpClient = new DefaultHttpClient();
		HttpPost post = new HttpPost(LOGIN);
		List<NameValuePair> param = new ArrayList<NameValuePair>();
		param.add(new BasicNameValuePair("acctname", user));
		param.add(new BasicNameValuePair("passwd", pass));
		post.setEntity(new UrlEncodedFormEntity(param, HTTP.UTF_8));
		httpClient.execute(post);
		CookieStore cookiestore = httpClient.getCookieStore();
		httpClient.getConnectionManager().shutdown();
		return cookiestore;
	}
	private ByteArrayInputStream getCouponEntity(CookieStore cookies) throws ClientProtocolException, IOException {
		DefaultHttpClient httpClient = new DefaultHttpClient();
		httpClient.setCookieStore(cookies);
		HttpGet get = new HttpGet(COUPON);
		HttpResponse res = httpClient.execute(get);
		ByteArrayInputStream in = new ByteArrayInputStream(EntityUtils.toByteArray(res.getEntity()));
		httpClient.getConnectionManager().shutdown();
		return in;
	}
	private ByteArrayInputStream getFastInfo(CookieStore cookies) throws ClientProtocolException, IOException {
		DefaultHttpClient httpClient = new DefaultHttpClient();
		httpClient.setCookieStore(cookies);
		HttpGet get = new HttpGet(FAST);
		HttpResponse res = httpClient.execute(get);
		ByteArrayInputStream in = new ByteArrayInputStream(EntityUtils.toByteArray(res.getEntity()));
		httpClient.getConnectionManager().shutdown();
		return in;
	}
	private ByteArrayInputStream pickupTable(ByteArrayInputStream is, String marker) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(is)); 
		StringBuilder sb = new StringBuilder();
		String s;
		boolean content = false;
		while((s = br.readLine()) != null) {
			if (s.contains(marker)) 
				content = true;
			if (content) {
				sb.append(s).append('\n');
				if (s.contains("</table>")) {
					break;
				}
			}
		}
		return new ByteArrayInputStream(sb.toString().getBytes());
	}
	private static final String LOGIN="https://ssl.excite.co.jp/idcenter/login/?_cn=proxy&pname=bbe&brand=xct&" +
			"targeturl=https%3A%2F%2Fssl.excite.co.jp%2Fbb%2Fcdn%2Flte%2Fdocomo%2Fcoupon%2F";
	private static final String COUPON="https://ssl.excite.co.jp/bb/cdn/lte/docomo/coupon/";
	private static final String FAST="https://ssl.excite.co.jp/bb/cdn/lte/docomo/onoff/";
	private CookieStore cookies;
	class ShowCoupon extends AsyncTask<String, Integer, Coupon> {
		private ProgressDialog dialog;
		@Override
		protected void onPreExecute() {
			dialog = new ProgressDialog(MainActivity.this);
			dialog.setTitle(getString(R.string.getting_title));
			dialog.setMessage(getString(R.string.wait));
			dialog.setIndeterminate(false);
			dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
			dialog.setCancelable(false);
			dialog.show();
		}
		@Override
		protected Coupon doInBackground(String... params) {
			Coupon coupon = new Coupon();
			try {
				cookies = getLoginCookie(params[0], params[1]);
				ByteArrayInputStream is = getCouponEntity(cookies);
				is = pickupTable(is, "\"o2\"");
				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
				DocumentBuilder builder = factory.newDocumentBuilder();
				Document document = builder.parse(is);
				NodeList td = document.getElementsByTagName("td");
				for (int i = 0; i < td.getLength(); i += 2)
					coupon.setRemain(i / 2, td.item(i).getTextContent());
				for (int i = 1; i < td.getLength(); i += 2)
					coupon.setMonth((i - 1) / 2, td.item(i).getTextContent());
				is = getFastInfo(cookies);
				is = pickupTable(is, "\"o2 txtC\"");
				factory = DocumentBuilderFactory.newInstance();
				builder = factory.newDocumentBuilder();
				document = builder.parse(is);
				td = document.getElementsByTagName("td");
				SIM sim = null;
				for(int i = 0; i < td.getLength(); i++)
					switch(i % 5) {
						case 0:
							sim = new SIM();
							break;
						case 1:
							sim.setFast(td.item(i).getTextContent().equals("ON"));
							break;
						case 4:
							sim.setTel(td.item(i).getTextContent());
							coupon.setSIM(i / 5, sim);
							break;
					}
			} catch (ClientProtocolException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (ParserConfigurationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			return coupon;
		}
		@Override
		protected void onPostExecute(Coupon coupon) {
			int remain_ids[] = new int[] {R.id.FieldToral, R.id.Field1, R.id.Field2, R.id.Field3, R.id.Field4};
			int date_ids[] = new int[] {R.id.Remain1, R.id.Remain2, R.id.Remain3, R.id.Remain4};
			int sim_ids[] = new int[] {R.id.Sim1OnOff, R.id.Sim1TelNo, R.id.Sim2OnOff, R.id.Sim2TelNo, R.id.Sim3OnOff, R.id.Sim3TelNo};
			boolean show[] = new boolean[] {true, true, true};
			int start = 0;
			TelephonyManager telmgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
			String telno = telmgr.getLine1Number();
			for(int i = 0; i < remain_ids.length; i ++) {
				TextView v = (TextView) findViewById(remain_ids[i]);
				v.setText(coupon.getRemain(i));
			}
			for (int i = 0; i < date_ids.length; i++) {
				TextView v = (TextView) findViewById(date_ids[i]);
				v.setText(String.format("%1$tB", coupon.getMonth(i)));
			}
			Pattern p = Pattern.compile("(\\d+)-(\\d+)-(\\d+)");
			for(int i = 0; i < 3; i++) {
				String simtel = coupon.getSIM(i).getTel();
				Matcher m = p.matcher(simtel);
				m.find();
				simtel = m.group(1) + m.group(2) + m.group(3);
				if (simtel.equals(telno)) {
					show[i] = false;
					ToggleButton b = (ToggleButton) findViewById(R.id.Sim1OnOff);
					b.setChecked(coupon.getSIM(i).isFast());
					TextView v = (TextView) findViewById(R.id.Sim1TelNo);
					v.setText(coupon.getSIM(i).getTel());
					start = 2;
				}
			}
			for (int i = start; i < sim_ids.length; i += 2) {
				for(int j = 0; j < show.length; j++) {
					if (!show[j])
						continue;
					ToggleButton b = (ToggleButton) findViewById(sim_ids[i]);
					b.setChecked(coupon.getSIM(j).isFast());
					TextView v = (TextView) findViewById(sim_ids[i+1]);
					v.setText(coupon.getSIM(j).getTel());
					show[j] = false;
					break;
				}
			}
			dialog.dismiss();
		}
	}
	class UpdateSw extends AsyncTask<String, Void, Void> {
		private String tel;
		private boolean state; 
		private ProgressDialog dialog;
		public UpdateSw(String tel, boolean state) {
			this.tel = tel;
			this.state = state;
		}
		private void applystate(List<NameValuePair> param) throws ClientProtocolException, IOException {
			DefaultHttpClient httpClient = new DefaultHttpClient();
			httpClient.setCookieStore(cookies);
			HttpPost post = new HttpPost(FAST);
			post.setEntity(new UrlEncodedFormEntity(param, HTTP.UTF_8));
			HttpResponse res = httpClient.execute(post);
			ByteArrayInputStream in = new ByteArrayInputStream(EntityUtils.toByteArray(res.getEntity()));
			httpClient.getConnectionManager().shutdown();
			BufferedReader br = new BufferedReader(new InputStreamReader(in)); 
			param = new ArrayList<NameValuePair>();
			String s;
			while((s = br.readLine()) != null) {
				if (!s.contains("_return") && s.contains("<input")) {
					int name = s.indexOf("name=") + 6;
					int value = s.indexOf("value") + 7;
					param.add(new BasicNameValuePair(s.substring(name, s.indexOf('"', name)), s.substring(value, s.indexOf('"', value))));
				}
			}
			httpClient = new DefaultHttpClient();
			httpClient.setCookieStore(cookies);
			post = new HttpPost(FAST);
			post.setEntity(new UrlEncodedFormEntity(param, HTTP.UTF_8));
			httpClient.execute(post);
			httpClient.getConnectionManager().shutdown();
		}
		protected void onPreExecute() {
			dialog = new ProgressDialog(MainActivity.this);
			dialog.setTitle(getString(R.string.apply));
			dialog.setMessage(getString(R.string.wait));
			dialog.setIndeterminate(false);
			dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
			dialog.setCancelable(false);
			dialog.show();
		}
		@Override
		protected Void doInBackground(String... arg0) {
			// TODO Auto-generated method stub
			try {
				cookies = getLoginCookie(arg0[0], arg0[1]);
				ByteArrayInputStream is = getFastInfo(cookies);
				BufferedReader br = new BufferedReader(new InputStreamReader(is)); 
				String s;
				List<NameValuePair> param = new ArrayList<NameValuePair>();
				while((s = br.readLine()) != null) {
					if (!s.contains("<td>") && s.contains("<input")) {
						int name = s.indexOf("name=") + 6;
						int value = s.indexOf("value") + 7;
						param.add(new BasicNameValuePair(s.substring(name, s.indexOf('"', name)), s.substring(value, s.indexOf('"', value))));
					}
				}
				is.reset();
				is = pickupTable(is, "\"o2 txtC\"");
				DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
				DocumentBuilder builder = factory.newDocumentBuilder();
				Document document = builder.parse(is);
				NodeList td = document.getElementsByTagName("td");
				boolean curstate = false;
				String simname = null;
				String simvalue = null;
				for(int i = 0; i < td.getLength(); i++)
					switch(i % 5) {
						case 0:
							NodeList input = td.item(i).getChildNodes();
							NamedNodeMap map = input.item(0).getAttributes();
							simname = map.getNamedItem("name").getNodeValue();
							simvalue = map.getNamedItem("value").getNodeValue();
							break;
						case 1:
							curstate= td.item(i).getTextContent().equals("ON");
							break;
						case 4:
							if(td.item(i).getTextContent().equals(tel) &&
									curstate != state) {
								param.add(new BasicNameValuePair(simname, simvalue));
								applystate(param);
							}
							break;
					}
			} catch (ClientProtocolException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ParserConfigurationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			return null;
		}
		@Override
		protected void onPostExecute(Void arg0) {
			dialog.dismiss();
		}		
	}
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		int sim_ids[] = new int[] {R.id.Sim1OnOff, R.id.Sim2OnOff, R.id.Sim3OnOff};
		for (int i = 0; i < sim_ids.length; i++) {
			ToggleButton b = (ToggleButton) findViewById(sim_ids[i]);
			b.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View arg0) {
					// TODO Auto-generated method stub
					int sim_ids[] = new int[] {R.id.Sim1OnOff, R.id.Sim1TelNo, R.id.Sim2OnOff, R.id.Sim2TelNo, R.id.Sim3OnOff, R.id.Sim3TelNo};
					for (int i = 0; i < sim_ids.length; i += 2) {
						if (findViewById(sim_ids[i]) == arg0) {
							TextView t = (TextView) findViewById(sim_ids[i + 1]);
							String tel = t.getText().toString();
							DBHelper dbhelper = new DBHelper(MainActivity.this);
							SQLiteDatabase db = dbhelper.getWritableDatabase();
							Cursor cur = db.query("account", new String[]{"rowid", "user", "password"}, null, null, null, null, null);
							if(cur.moveToFirst()) {
								String user = cur.getString(cur.getColumnIndex("user"));
								String pass = cur.getString(cur.getColumnIndex("password"));
								db.close();
								new UpdateSw(tel, ((ToggleButton)arg0).isChecked()).execute(user, pass);
							}
						}
							
					}
				}
			});
		}
		updateCoupon();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
		super.onActivityResult(requestCode, resultCode, intent);
		if(requestCode == 0) {
			if(resultCode == RESULT_OK) {
				updateCoupon();
			}
		}
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == R.id.menu_login) {
			Intent intent = new Intent(this,LoginActivity.class);
			startActivityForResult(intent, 0);
			return true;
		} else {
			return super.onOptionsItemSelected(item);
		}
	}
	
	private void updateCoupon() {
		DBHelper dbhelper = new DBHelper(this);
		SQLiteDatabase db = dbhelper.getWritableDatabase();
		Cursor cur = db.query("account", new String[]{"rowid", "user", "password"}, null, null, null, null, null);
		if(!cur.moveToFirst()) {
			db.close();
			Intent intent = new Intent(this,LoginActivity.class);
			startActivityForResult(intent, 0);
		} else {
			String user = cur.getString(cur.getColumnIndex("user"));
			String pass = cur.getString(cur.getColumnIndex("password"));
			db.close();
			new ShowCoupon().execute(new String[] {user, pass});
		}
		
	}
}
